package org.e_gold.service.impl;

import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;
import org.e_gold.dao.CookieDAO;
import org.e_gold.dto.Cookies;
import org.e_gold.service.CookieService;
import org.e_gold.util.Constant;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

@Component
public class _NavigatorService implements Constant, InitializingBean {

    private static final Logger logger = Logger.getLogger(_NavigatorService.class);
    Connection connection;
    protected static Cookies cookies;
    protected static Map<String, String> headers;

    @Autowired
    private CookieService cookieService;

    @Autowired
    private CookieDAO cookieDAO;

    @Override
    public void afterPropertiesSet() throws Exception {

        // init header + cookies
        headers = prepareBasicHeaders();
        if (cookieDAO.findAll() != null && cookieDAO.findAll().size() > 0) {
            // re-store cookie for logined session or basic session for the first time
            if (cookies == null) {
                cookies = new Cookies();
            }
            if (cookies.getCookies() == null) {
                cookies.setCookies(cookieDAO.findAll());
            }
            headers.put(COOKIE, cookies.getCookie());
        } else {
            try {
                redirectNavigator(DEFAULT_URL);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public Connection navigator(String url) {

        Connection connection = Jsoup.connect(url);
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            connection.header(entry.getKey(), entry.getValue());
        }
        if (cookies != null && cookies.getCookieMap() != null && cookies.getCookieMap().size() > 0) {
            connection.cookies(cookies.getCookieMap());
            connection.header(COOKIE, cookies.getCookie());
        }
        connection.followRedirects(false);
        return connection;
    }

    public Map<String, String> prepareBasicHeaders() {

        Map<String, String> basicHeader = new HashMap<String, String>();
        basicHeader.put(ACCEPT, ACCEPT_DATA);
        basicHeader.put(ACCEPT_ENCODING, ACCEPT_ENCODING_DATA);
        basicHeader.put(ACCEPT_LANGUAGE, ACCEPT_LANGUAGE_DATA);
        basicHeader.put(CONNECTION, CONNECTION_DATA);
        basicHeader.put(HOST, HOST_DATA);
        basicHeader.put(USER_AGENT, USER_AGENT_DATA);
        basicHeader.put(CACHE_CONTROL, CACHE_CONTROL_DATA);
        basicHeader.put(PRAGMA, PRAGMA_DATA);
        return basicHeader;
    }

    public Document redirectNavigator(String url) throws Exception {

        Document doc = null;
        try {
            connection = navigator(url).timeout(30000);
            doc = connection.get();
            while (responseCode(connection) == HttpStatus.FOUND.value()) {
                String redirectLocation = connection.response().header(LOCATION);
                if (cookies == null) {
                    cookies = new Cookies();
                }
                cookies.putNewCookies(connection.response().cookies());
                cookieService.saveCookies(cookies);
                connection = navigator(redirectLocation);
                doc = connection.get();
            }
        } catch (Exception e) {
            logger.error("redirectNavigator error : " + url);
            throw e;
        }

        return doc;
    }

    public Document postForm(String url, Map<String, String> formData) {

        Document doc = null;
        try {
            connection = navigator(url).timeout(30000).data(formData);
            doc = connection.post();
            while (responseCode(connection) == HttpStatus.FOUND.value()) {
                headers.remove(CONTENT_TYPE);
                cookies.putNewCookies(connection.response().cookies());
                // update current cookie
                cookieService.saveCookies(cookies);
                String redirectLocation = connection.response().header(LOCATION);
                connection = navigator(redirectLocation);
                doc = connection.get();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return doc;
    }

    public int responseCode(Connection connection) {

        return connection.response().statusCode();
    }

}
